using System;
using System.Collections.Generic;
using System.Text;
using VSSDKAssist.Assets.Actions.Base;
using EnvDTE;
using Microsoft.Practices.RecipeFramework;
using VSSDKAssist.Assets.Actions.VisualStudio;
using VSSDKAssist.Assets.Helpers;

namespace VSSDKAssist.Recipes.ConfigureSplashAboutScreens
{
	/// <summary>
	/// Action thats configures VS splash screen
	/// </summary>
	public class ConfigureSplashScreenAction : ActionBase
	{
		#region Properties
		private CodeClass codeClass;

		/// <summary>
		/// Gets or sets the code class.
		/// </summary>
		/// <value>The code class.</value>
		[Input(Required = true)]
		public CodeClass CodeClass
		{
			get { return codeClass; }
			set { codeClass = value; }
		}

		private string interfaceName;

		/// <summary>
		/// Gets or sets the name of the interface.
		/// </summary>
		/// <value>The name of the interface.</value>
		[Input(Required = true)]
		public string InterfaceName
		{
			get { return interfaceName; }
			set { interfaceName = value; }
		}

		private string ivsInstalledProductContent;

		/// <summary>
		/// Gets or sets the content of the I vs installed product.
		/// </summary>
		/// <value>The content of the I vs installed product.</value>
		[Input(Required = true)]
		public string IVsInstalledProductContent
		{
			get { return ivsInstalledProductContent; }
			set { ivsInstalledProductContent = value; }
		}

		private bool generateSplash;

		/// <summary>
		/// Gets or sets a value indicating whether [generate splash].
		/// </summary>
		/// <value><c>true</c> if [generate splash]; otherwise, <c>false</c>.</value>
		[Input(Required = true)]
		public bool GenerateSplash
		{
			get { return generateSplash; }
			set { generateSplash = value; }
		}
		#endregion

		/// <summary>
		/// Called when [execute].
		/// </summary>
		protected override void OnExecute()
		{
			if(this.generateSplash)
			{
				if(FindImplementedInterface(this.InterfaceName) == null)
				{
					AddIVsInstalledProductDeclaration();
					AddIVsInstalledProductImplementation();
				}
				else
				{
					//Recreate implementation
					RemoveIVsInstalledProductImplementation();
					AddIVsInstalledProductImplementation();
				}
			}
			else
			{
				RemoveIVsInstalledProductDeclaration();
				RemoveIVsInstalledProductImplementation();
			}
		}

		#region Private Implementation
		private void AddIVsInstalledProductDeclaration()
		{
			this.codeClass.AddImplementedInterface(this.interfaceName, -1);
		}

		private void RemoveIVsInstalledProductDeclaration()
		{
			CodeElement implementedInterface = FindImplementedInterface(this.InterfaceName);

			if(implementedInterface != null)
			{
				this.codeClass.RemoveInterface(implementedInterface);
			}
		}

		private void AddIVsInstalledProductImplementation()
		{
			FileCodeModelHelper.InsertTextToCodeElement(
				this.CodeClass as CodeElement, this.IVsInstalledProductContent);
		}

		private void RemoveIVsInstalledProductImplementation()
		{
			CodeElementsIterator iterator = new CodeElementsIterator(this.codeClass as CodeElement);
			List<CodeElement> elementsToRemove = new List<CodeElement>();

			foreach(CodeElement element in iterator)
			{
				if(element is CodeFunction && 
					(element.Name == "IdBmpSplash" ||
					element.Name == "IdIcoLogoForAboutbox" ||
					element.Name == "OfficialName" ||
					element.Name == "ProductDetails" ||
					element.Name == "ProductID" ||
					element.Name == "GetResourceString"
					))
				{
					elementsToRemove.Add(element);
				}
			}

			foreach(CodeElement element in elementsToRemove)
			{
				this.codeClass.RemoveMember(element);
			}
		}

		private CodeElement FindImplementedInterface(string intName)
		{
			foreach(CodeElement element in this.codeClass.ImplementedInterfaces)
			{
				if(IsTypeNameEquals(element.Name, intName) ||
					IsTypeNameEquals(element.FullName, intName))
				{
					return element;
				}
			}

			return null;
		}

		private static bool IsTypeNameEquals(string name, string name1)
		{
			//TODO: Verify Microsoft.VisualStudio.Shell.Interop.IVsInstalledProduct == IVsInstalledProduct == or any other alias
			return name.Equals(name1, StringComparison.OrdinalIgnoreCase);
		}
		#endregion
	}
}